package com.searchparking.BUS;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.google.android.gms.maps.model.LatLng;

public class DirectionsJSONParser {
	String TAG_ROUTES = "routes";
	String TAG_LEGS = "legs";

	String TAG_DISTANCE = "distance";
	String TAG_DURATION = "duration";
	String TAG_TEXT = "text";

	String TAG_STEPS = "steps";
	String TAG_POLYLINE = "polyline";
	String TAG_POINTS = "points";

	String TAG_DISTANCE_STEPS = "distance_steps";
	String TAG_DURATION_STEPS = "duration_steps";
	String TAG_HTML_INSTRUCTIONS = "html_instructions";

	String TAG_LAT = "lat";
	String TAG_LNG = "lng";

	// list instruction
	public static List<HashMap<String, String>> listInstruction;

	public DirectionsJSONParser() {
		listInstruction = new ArrayList<HashMap<String, String>>();
	}

	/**
	 * Receives a JSONObject and returns a list of lists containing latitude and
	 * longitude
	 */
	public List<List<HashMap<String, String>>> parse(JSONObject jObject) {
		List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String, String>>>();
		JSONArray jRoutes = null;
		JSONArray jLegs = null;
		JSONArray jSteps = null;
		JSONObject jDistance = null;
		JSONObject jDuration = null;

		try {
			jRoutes = jObject.getJSONArray(TAG_ROUTES);
			/** Traversing all routes */
			for (int i = 0; i < jRoutes.length(); i++) {

				jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray(TAG_LEGS);
				List<HashMap<String, String>> path = new ArrayList<HashMap<String, String>>();
				/** Traversing all legs */

				for (int j = 0; j < jLegs.length(); j++) {

					/** Getting distance from the json data */
					jDistance = ((JSONObject) jLegs.get(j))
							.getJSONObject(TAG_DISTANCE);
					HashMap<String, String> hmDistance = new HashMap<String, String>();
					hmDistance.put(TAG_DISTANCE, jDistance.getString(TAG_TEXT));

					/** Getting duration from the json data */
					jDuration = ((JSONObject) jLegs.get(j))
							.getJSONObject(TAG_DURATION);
					HashMap<String, String> hmDuration = new HashMap<String, String>();
					hmDuration.put(TAG_DURATION, jDuration.getString(TAG_TEXT));

					/** Adding distance object to the path */
					path.add(hmDistance);

					/** Adding duration object to the path */
					path.add(hmDuration);

					jSteps = ((JSONObject) jLegs.get(j))
							.getJSONArray(TAG_STEPS);
					int ij = 0;
					/** Traversing all steps */
					for (int k = 0; k < jSteps.length(); k++) {
						// add Instruction
						setListInstruction((JSONObject) jSteps.get(k));

						String polyline = "";
						polyline = (String) ((JSONObject) ((JSONObject) jSteps
								.get(k)).get(TAG_POLYLINE)).get(TAG_POINTS);
						List<LatLng> list = this.decodePoly(polyline);

						/** Traversing all points */
						for (int l = 0; l < list.size(); l++) {
							
							HashMap<String, String> hm = new HashMap<String, String>();
							hm.put(TAG_LAT,
									Double.toString((list.get(l)).latitude));
							hm.put(TAG_LNG,
									Double.toString((list.get(l)).longitude));
							/*
							 * Log.d("item1", "latitude:>" +
							 * Double.toString((list.get(l)).latitude));
							 * Log.d("item1", "longitude:>" +
							 * Double.toString((list.get(l)).longitude));
							 */
							path.add(hm);
						}
					}
					
				}
				routes.add(path);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		} catch (Exception e) {
		}

		return routes;
	}

	// get list Instruction
	public static List<HashMap<String, String>> getListInstruction() {
		return listInstruction;
	}

	// set list Instruction
	public void setListInstruction(JSONObject jSteps) {
		// instruction
		HashMap<String, String> instruction = new HashMap<String, String>();
		String distance, duration, html_instructions;
		try {
			distance = (String) ((JSONObject) jSteps.get(TAG_DISTANCE))
					.get(TAG_TEXT);
			duration = (String) ((JSONObject) jSteps.get(TAG_DURATION))
					.get(TAG_TEXT);
			html_instructions = (String) jSteps.get(TAG_HTML_INSTRUCTIONS);

			// add hashmap
			instruction.put(TAG_DISTANCE_STEPS, distance);
			instruction.put(TAG_DURATION_STEPS, duration);
			instruction.put(TAG_HTML_INSTRUCTIONS, html_instructions);

		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// add list
		listInstruction.add(instruction);
	}

	/**
	 * Method to decode polyline points Courtesy :
	 * jeffreysambells.com/2010/05/27
	 * /decoding-polylines-from-google-maps-direction-api-with-java
	 * */
	private List<LatLng> decodePoly(String encoded) {

		List<LatLng> poly = new ArrayList<LatLng>();
		int index = 0, len = encoded.length();
		int lat = 0, lng = 0;

		while (index < len) {
			int b, shift = 0, result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;

			shift = 0;
			result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;

			LatLng p = new LatLng(((lat / 1E5)), ((lng / 1E5)));
			poly.add(p);
		}

		return poly;
	}
}